package net.xisberto.phonetodesktop;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.util.Log;

import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxUnlinkedException;

public class LinkListService extends Service {
	
	public static final String LINKLIST_ACTION = "net.xisberto.phonetodesktop.linklist",
			DELETE_LINK_ACTION = "net.xisberto.phonetodesktop.deletelink",
			MARK_VISITED_ACTION = "net.xisberto.phonetodesktop.markvisited",
			EXTRA_IS_EMPTY = "is_empty",
			EXTRA_VECTOR = "link_list";
	
	private Looper looper;
	private Handler handler;
	private Intent intent;
	private DropboxSynced dropbox;
	
	private Runnable sendUpdatesToUI = new Runnable() {
		@Override
		public void run() {
			synchronized (this) {
				Log.i(getPackageName(), intent.getAction());
				if (intent.getAction().equals(DELETE_LINK_ACTION)) {
					Log.i(getApplicationInfo().packageName, "Should delete "+intent.getIntExtra("item_index", -1));
					deleteLink(intent.getIntExtra("item_index", -1));
				} else if (intent.getAction().equals(MARK_VISITED_ACTION)) {
					Log.i(getApplicationInfo().packageName, "Should mark "+intent.getIntExtra("item_index", -1));
				}
				broadcastLinkList();	
			}
		}
	};
	
	@Override
	public void onCreate() {
		super.onCreate();
		intent = new Intent(LINKLIST_ACTION);
		dropbox = new DropboxSynced(getApplicationContext());
		
		HandlerThread thread = new HandlerThread("LinkListThread", Process.THREAD_PRIORITY_BACKGROUND);
		thread.start();
		
		looper = thread.getLooper();
		handler = new Handler(looper);
		
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(getApplicationContext().getPackageName(), "service starting");
		this.intent.setAction(intent.getAction());
		handler.post(sendUpdatesToUI);
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		Log.i(getApplicationContext().getPackageName(), "service done");
	}

	@Override
	public IBinder onBind(Intent intent) {
		return new Binder();
	}
	
	private JSONArray getLinkList() {
		JSONArray array = null;
		Log.i(getApplicationInfo().packageName, "downloading link list");
    	ByteArrayOutputStream file = new ByteArrayOutputStream();
    	try {
			file = dropbox.download(DropboxSynced.FILENAME);
		} catch (DropboxUnlinkedException e) {
			Log.e(getApplicationInfo().packageName, "Unlinked when downloading");
		} catch (DropboxException e) {
			Log.e(getApplicationInfo().packageName, "Generic error when downloading");
		}

    	if (file.size() == 0) {
    		intent.putExtra(EXTRA_IS_EMPTY, true);
    	} else {
    		//Initiate some variables
    		JSONObject json_output = null;
    		try {
    			//Parse the downloaded into a JSONObject and obtains the link list
				json_output = new JSONObject(file.toString());
    			array = json_output.getJSONArray("links_list");
    		} catch (JSONException e) {
    			Log.e(getApplicationInfo().packageName, "JSON error when downloading");
    		}
    	}
    	return array;
	}
	
	private void putLinkList(JSONArray link_list) {
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		try {
			byte[] buffer = link_list.toString(4).getBytes();
			outputStream.reset();
			outputStream.write(buffer);
			outputStream.flush();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			dropbox.upload(outputStream, DropboxSynced.FILENAME);
		} catch (DropboxUnlinkedException e) {
			e.printStackTrace();
		} catch (DropboxException e) {
			e.printStackTrace();
		}
	}
	
	private void deleteLink(int index) {
		Log.i(getPackageName(), index+"");
		if (index < 0) {
			return;
		}
		JSONArray array = getLinkList();
		JSONArray new_array = new JSONArray();
		for (int i = 0; i < array.length(); i++) {
			if (i == index) {
				continue;
			}
			try {
				new_array.put(array.getJSONObject(i));
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		putLinkList(new_array);
	}
	
	private void broadcastLinkList() {
		JSONArray array = getLinkList();
		ArrayList<Map<String,String>> vector = new ArrayList<Map<String,String>>();
		for (int i = 0; i < array.length(); i++) {
			//Get the link, put it in a HashMap, and the Map in the Vector
			try {
				JSONObject link = array.getJSONObject(i);
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("url", link.getString("url"));
				map.put("visited", new Boolean(link.getBoolean("visited")).toString());
				vector.add(map);
			} catch (JSONException e) {
				Log.e(getApplicationInfo().packageName, "JSON error when parsing");
			}
			
		}
			
		if (vector.size() == 0) {
			intent.putExtra(EXTRA_IS_EMPTY, true);
		} else {
			intent.putExtra(EXTRA_IS_EMPTY, false);
			intent.putExtra(EXTRA_VECTOR, vector);
		}
    	
    	sendBroadcast(intent);
	}
}
